package com.mtcarpenter.stream;

import com.mtcarpenter.common.Fruit;
import com.mtcarpenter.common.FruitDataTest;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

/**
 * @Author: mtcarpenter
 * @describe 中间操作
 * @Date: 2019/10/6
 * @Version 1.0
 */
public class StreamApi02Test {

    /**
     * filter-对元素进行过滤
     */
    @Test
    public void test01() {
        // 获取我们模拟的 fruit 数组数据
        List<Fruit> fruites = FruitDataTest.getFruites();
        // 创建数据流
        Stream<Fruit> stream = fruites.stream();
        System.out.println("价格（price）大于 30 的水果 ");
        // 筛选 price 价格大于 30 的水果
        stream.filter(s -> s.getPrice() > 30.0).forEach(System.out::println);
    }

    /**
     * filter-对元素进行过滤，可以复用方式
     */
    @Test
    public void test02() {
        List<Fruit> fruites = FruitDataTest.getFruites();
        System.out.println("价格（price）大于 30 的水果 ,方法复用");
        List<Fruit> fruits = filterFruitPrice(fruites, s -> s.getPrice() > 30);
        fruits.forEach(System.out::println);
    }

    public List<Fruit> filterFruitPrice(List<Fruit> fruits, Predicate<Fruit> predicate) {
        List<Fruit> list = new ArrayList<>();
        for (Fruit fruit : fruits) {
            if (predicate.test(fruit)) {
                list.add(fruit);
            }
        }
        return list;
    }

    /**
     * distinct - 去除重复元素
     */
    @Test
    public void test03() {
        List<Fruit> fruites = FruitDataTest.getFruites();
        // 复制 模拟数据的前两条继续追加
        fruites.add(new Fruit(1, "苹果", 100, 10, 2));
        fruites.add(new Fruit(2, "葡萄", 90, 19, 1));
        fruites.add(new Fruit(1, "苹果", 100, 10, 2));
        System.out.println("数据没有去重");
        fruites.stream().forEach(System.out::println);
        System.out.println("\n distinct() 数据去重");
        fruites.stream().distinct().forEach(System.out::println);
    }

    /**
     * map - 映射
     */
    @Test
    public void test04() {
        List<Fruit> fruites = FruitDataTest.getFruites();
        // 取出集合中所有的水果名称
        System.out.println("lambda - map() 取出水果名称 ");
        fruites.stream().map(s -> s.getName()).forEach(System.out::println);
        System.out.println("\n lambda 方法引用 - map() 取出水果名称 ");
        fruites.stream().map(Fruit::getName).forEach(System.out::println);
    }


    /**
     * 集合 add 和 addAll
     */
    @Test
    public void test05() {
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        ArrayList list2 = new ArrayList();
        list2.add(4);
        list2.add(5);
        list2.add(6);
        //list1.add(list2); //map
        list1.addAll(list2);  // floatmap
        System.out.println(list1);
    }

    /**
     * flatMap- 一个或多个流合并成一个新流
     */
    @Test
    public void test06() {
        // map 则需要通过两次 forEach 才能输出结果
        Stream<Stream<Integer>> streamStream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6))
                .map(s -> s.stream());
        streamStream.forEach(s -> {
            s.forEach(System.out::print);
            System.out.println("---->");
        });
        // flatMap 形成一个新的流 一次性输出
        Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6)).flatMap(s -> s.stream()).forEach(s -> {
            System.out.print(s + ", ");
        });
    }

    /**
     * limit - 限流
     */
    @Test
    public void test07(){
        List<Fruit> fruites = FruitDataTest.getFruites();
        // 取出前5条
        System.out.println("limit 限流 前 3 条");
        fruites.stream().limit(3).forEach(System.out::println);
    }

    /**
     * skip 跳过元素
     */
    @Test
    public void test08(){
        List<Fruit> fruites = FruitDataTest.getFruites();
        // 取出第 3 条后面的数据
        System.out.println("skip 取出第 3 条后面的数据");
        fruites.stream().skip(3).forEach(System.out::println);
    }

    /**
     * sorted 排序
     */
    @Test
    public void test09(){
        // 数组 排序 sorted() 无参
        List<Integer> nums = Arrays.asList(1, 2, 3, 6, 8, 7, 5);
        nums.stream().sorted().forEach(System.out::print);

        List<Fruit> fruites = FruitDataTest.getFruites();

        System.out.println("\n sorted() 指定条件比较");
        // 按照 价格进行比较
        fruites.stream().sorted((e1,e2)->Double.compare(e1.getPrice(),e2.getPrice())).forEach(System.out::println);
        System.out.println("******** 优化之后 ********");
        // 优化代码
        fruites.stream().sorted(Comparator.comparingDouble(Fruit::getPrice)).forEach(System.out::println);
    }


    /**
     * peek - 数据状态
     */
    @Test
    public void test10(){
        List<Fruit> fruites = FruitDataTest.getFruites();
        fruites.stream().peek(s-> System.out.println(s.getId())).forEach(System.out::println);

    }
}
